package com.oauth.facebook.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;

/**
 * Allows in-place editing of Labels. Activated via click.
 * 
 * The reference value is always the one in the label and change events are only
 * fired after editing has finished.
 * 
 * TODO make it optional how to activate the editing mode
 * 
 * @author Araivnd S
 * 
 */
public class EditableLabel extends Composite implements HasValue<String> {

	private static EditableLabelUiBinder uiBinder = GWT
			.create(EditableLabelUiBinder.class);

	interface EditableLabelUiBinder extends UiBinder<Widget, EditableLabel> {
	}

	protected static String DEFAULT_UPDATE_BUTTON_TEXT = "Update";
	protected static String DEFAULT_CANCEL_BUTTON_TEXT = "Cancel";

	protected String originalText;

	@UiField
	protected Label editLabel;

	@UiField
	protected DeckPanel deckPanel;

	@UiField
	protected TextArea editBox;

	@UiField
	protected FocusPanel focusPanel;

	@UiField
	protected Button updateButton;

	@UiField
	protected Button cancelButton;

	@UiField
	protected FocusPanel editingPanel;

	public EditableLabel() {
		initWidget(uiBinder.createAndBindUi(this));
		deckPanel.showWidget(0);
		updateButton.setText(DEFAULT_UPDATE_BUTTON_TEXT);
		cancelButton.setText(DEFAULT_CANCEL_BUTTON_TEXT);

		updateButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent pEvent) {
				System.out.println("Inside update click");
				switchToLabel();
			}
		});
		editingPanel.addBlurHandler(new BlurHandler() {

			@Override
			public void onBlur(BlurEvent pEvent) {
				switchToCancel();
			}
		});

		cancelButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent pEvent) {
				switchToCancel();
			}
		});
	}

	public void setButtonText(String updateText, String cancelText) {
		updateButton.setText(updateText);
		cancelButton.setText(cancelText);
	}

	@UiHandler("focusPanel")
	public void onFocus(FocusEvent event) {
		switchToEdit();
	}

	@UiHandler("editLabel")
	public void onClick(ClickEvent event) {
		switchToEdit();
	}

	@UiHandler("editingPanel")
	public void onBlur(BlurEvent event) {
		switchToCancel();
	}

	@UiHandler("editBox")
	public void onKeyPress(KeyPressEvent event) {
		if (event.getCharCode() == KeyCodes.KEY_ENTER) {
			switchToLabel();
		} else if (event.getCharCode() == KeyCodes.KEY_ESCAPE) {
			switchToCancel();
		}
	}

	public void switchToCancel() {
		if (deckPanel.getVisibleWidget() == 0)
			return;
		deckPanel.showWidget(0);
	}

	public void switchToEdit() {
		if (deckPanel.getVisibleWidget() == 1)
			return;
		editBox.setText(getValue());
		deckPanel.showWidget(1);
		editBox.setFocus(true);
	}

	public void switchToLabel() {
		/*
		 * if (deckPanel.getVisibleWidget() == 0) return;
		 */
		System.out.println("Setting value");
		setValue(editBox.getText(), true); // fires events, too
		System.out.println("After set:" + editLabel.getText());
		deckPanel.showWidget(0);
	}

	@Override
	public HandlerRegistration addValueChangeHandler(
			ValueChangeHandler<String> handler) {
		return addHandler(handler, ValueChangeEvent.getType());
	}

	@Override
	public String getValue() {
		return editLabel.getText();
	}

	@Override
	public void setValue(String value) {
		editLabel.setText(value);
		editBox.setText(value);
	}

	@Override
	public void setValue(String value, boolean fireEvents) {
		if (fireEvents)
			ValueChangeEvent.fireIfNotEqual(this, getValue(), value);
		setValue(value);
	}

}
